<?php
/**********************************************************************************
WIKINDX: Bibliographic Management system.
Copyright (C)

This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program;
if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

The WIKINDX Team 2007
sirfragalot@users.sourceforge.net
**********************************************************/
/*****
* USER class
*****/
class USER
{
// Constructor
	function USER($db, $vars = FALSE)
	{
		$this->db = $db;
		$this->vars = $vars;
		include_once("core/messages/ERRORS.php");
		$this->errors = new ERRORS();
		include_once("core/session/SESSION.php");
		$this->session = new SESSION();
		include_once("core/html/HTML.php");
		$this->html = new HTML();
		include_once("core/html/MISC.php");
		include_once("core/html/FORM.php");
		include_once("core/html/TABLE.php");
		include_once("core/template/TEMPLATE.php");
		$this->template = new TEMPLATE('content');
		include_once("core/messages/MESSAGES.php");
		$this->messages = new MESSAGES();
		include_once("core/messages/SUCCESS.php");
		$this->success = new SUCCESS();
	}
// Write user details to WKX_users
// If $admin = 0, this is a standard user.
// If $admin = 1, this is the initial configuration/reconfiguration and we need to insert superadmin details into the database.
// If $admin = 2, this is an admin editing or adding a user.
// a) the user may not change the username from this screen.
// Whe adding a user, we need to check there is not already $username (caseless) in the database.
// NB - returns FALSE in case of success, an error message in case of failure.
	function writeUser($add = TRUE, $admin = 0)
	{
		if(array_key_exists('username', $this->vars))
		{
			$username = $this->html->removeNl($this->vars['username']);
// check for existing usernames (remove current user from search if already logged in with setup_userId)
			$condition = " WHERE " . $this->db->formatField('username') . " = " . 
				$this->db->tidyInput($username);
			if($userId = $this->session->getVar('setup_userId') && !$add)
				$condition .= " AND " . $this->db->formatField('id') . " != " . 
				$this->db->tidyInput($userId);
// existing user with that username found (not this user)
			$recordset = $this->db->select(array('WKX_users'), array('id'), $condition);
			if($this->db->numRows($recordset))
				return $this->errors->text("inputError", "userExists");
		}
		$password = $this->html->removeNl($this->vars['password']);
		if(!$add) // update
		{
			if(!$admin) // user editing own details
			{
				$userId = $this->session->getVar('setup_userId');
				if(array_key_exists('cookie', $this->vars) && $this->vars['cookie'])
					$update['cookie'] = 'Y';
				else
				{
// remove any wikindx cookie that has been set
					include_once("core/cookie/COOKIE.php");
					$cookie = new COOKIE();
					$cookie->deleteCookie();
					$update['cookie'] = 'N';
				}
			}
			else if($admin == 1) // superadmin configuration - userId always 1 for superadmin
				$userId = 1;
			else if($admin == 2) // admin editing user
			{
				$userId = $this->vars['userId'];
				if(array_key_exists('admin', $this->vars) && $this->vars['admin'])
					$update['admin'] = 'Y';
				else
					$update['admin'] = 'N';
			}
			$recordset = $this->db->select(array('WKX_users'), array('password'), 
				" WHERE " . $this->db->formatField('id') . " = " . $this->db->tidyInput($userId));
// The encrypted password is displayed on the browser screen.  Need to check if it's unchanged as we don't 
// want to encrypt the encrypted password!
			if($this->db->numRows($recordset))
			{
				$this->pwdInputEncrypted = FALSE;
				$pwd = $this->db->fetchOne($recordset);
				if($password != $pwd)
					$password = crypt($password, strrev(time()));
				else
					$this->pwdInputEncrypted = TRUE;
			}
			$update['password'] = $password;
			if(array_key_exists('fullname', $this->vars) && 
				$fullname = $this->db->tidyInput($this->html->removeNl($this->vars['fullname'])))
				$update['fullname'] = $this->html->removeNl($this->vars['fullname']);
// Ensure it's set to NULL
			else
				$this->db->updateNull('WKX_users', array('fullname'), 
					" WHERE " . $this->db->formatField('id') . " = " . 
					$this->db->tidyInput($userId));
			if($admin == 1) // superadmin configuration
				$update['username'] = $username;
			else
				$update['email'] = $this->vars['email'];
			$this->db->update('WKX_users', $update, 
				" WHERE " . $this->db->formatField('id') . " = " . $this->db->tidyInput($userId));
		}
		else // insert new user
		{
			$password = crypt($password, strrev(time()));
			$field[] = 'username';
			$value[] = $username;
			$field[] = 'password';
			$value[] = $password;
			if(array_key_exists('email', $this->vars) && 
				$fullname = $this->html->removeNl($this->vars['email']))
			{
				$field[] = 'email';
				$value[] = $this->vars['email'];
			}
			if($admin == 1) // if == 0, default db field value is 'N'
			{
				$field[] = 'admin';
				$value[] = 'Y';
				$field[] = 'fullname';
				$value[] = 'superAdmin';
			}
			else if($admin == 2) // admin editing a user
			{
				if(array_key_exists('admin', $this->vars) && $this->vars['admin'])
				{
					$field[] = 'admin';
					$value[] = 'Y';
				}
			}
			if(array_key_exists('fullname', $this->vars) && 
				$fullname = $this->html->removeNl($this->vars['fullname']))
			{
				$field[] = 'fullname';
				$value[] = $fullname;
			}
			$this->db->insert('WKX_users', $field, $value);
			$userId = $this->db->lastAutoId('WKX_users');
// set the new WKX_users.notifyTimestamp and WKX_users.timestamp to current date
		$this->db->query("UPDATE `WKX_users` set `notifyTimestamp` = NOW(), `timestamp` = NOW() WHERE `id`=$userId");
// write userId to session if not adding a new user
			if(!$add)
				$this->session->setVar('setup_userId', $userId);
// insert preferences to table
			$this->writePreferences($userId);
		}
		return FALSE; // success!
	}
// Compare encrypted password.  Username and encrypted password now stored in WKX_users.
// Return FALSE for password not found or password doesn't match.
// Superadmin is always id = 1
	function checkPassword($username, $pwdInput)
	{
		$condition = " WHERE " . $this->db->formatField('username') . " = " . $this->db->tidyInput($username);
		$recordset = $this->db->select(array('WKX_users'), array("id", "password", "admin", "cookie"), 			
			$condition);
		if(!$this->db->numRows($recordset))
			return FALSE;
		$row = $this->db->fetchRow($recordset);
// only the superadmin may log on when multi user is not enabled
		if(!$this->session->getVar("setup_multiUser") && ($row['id'] != 1))
			return FALSE;
		if(crypt($pwdInput, $row['password']) != $row['password'])
			return FALSE;
// Logged in, now set up environment
		$this->environment($row, $username);
		return TRUE;
	}
// set up user environment on first logon
	function environment($row, $username = FALSE)
	{
// First delete any pre-existing session in case this user has been logging on and off as different users
		$this->session->clearAllSessionData();
		if($row['admin'] == 'Y')
			$this->session->setVar("setup_superadmin", TRUE);
		$this->session->setVar("setup_userId", $row['id']);
		$this->session->setVar("setup_write", TRUE);
		$this->session->delVar("setup_readOnly");
		$this->writeSessionPreferences($row['id']);
		$this->grabBibliographies();
// If $username, we are logging in without using a cookie.  Check if we require a cookie to be set.
		if(array_key_exists('cookie', $row) && ($row['cookie'] == 'Y'))
		{
			include_once("core/cookie/COOKIE.php");
			$cookie = new COOKIE();
			$cookie->storeCookie($username);
		}
	}
// Get users from WKX_users.  Return associative array of id => group.
	function grabAll($full = FALSE)
	{
		include_once("core/html/HTML.php");
		$html = new HTML();
		if($full)
			$recordset = $this->db->select(array("WKX_users"), array("id", "username", "fullname", "admin"), 
				'ORDER BY ' . $this->db->tidyInputClause('username'));
		else
			$recordset = $this->db->select(array("WKX_users"), array("id", "username"), 
				'ORDER BY ' . $this->db->tidyInputClause('username'));
		while($row = $this->db->loopRecordSet($recordset))
		{
			$users[$row['id']] = $html->dbToFormTidy($row['username']);
			if($full && $row['fullname'])
				$users[$row['id']] .= " (" . $html->dbToFormTidy($row['fullname']) . ")";
			if($full && ($row['admin'] == 'Y'))
				$users[$row['id']] .= " ADMIN";
		}
		if(isset($users))
			return $users;
		else
			return FALSE; // shouldn't ever happen but just in case....
	}
// insert/update user preferences
	function writePreferences($userId)
	{
// Set paging_start back to 0
		$this->session->setVar('mywikindx_pagingStart', 0);
		$preferences = array("paging", "pagingMaxLinks", "stringLimit", "language", "style", "template", 'pagingStyle', 
			"pagingTagCloud", "kwBibliography", "useBibtexKey", "useWikindxKey", "displayBibtexLink", "displayCmsLink");
		foreach($preferences as $pref)
		{
			if($pref == 'pagingStyle') // checkbox
			{
				if($this->session->getVar('setup_pagingStyle') == 'A')
					$updateArray["pagingStyle"] = 'A';
				else
					$updateArray["pagingStyle"] = 'N';
				continue;
			}
			if($pref == "kwBibliography") // checkbox
			{
				if($this->session->getVar("setup_kwBibliography"))
					$updateArray["kwBibliography"] = 'Y';
				else
					$updateArray["kwBibliography"] = 'N';
				continue;
			}
			if($pref == "useWikindxKey") // checkbox
			{
				if($this->session->getVar("setup_useWikindxKey"))
					$updateArray["useWikindxKey"] = 'Y';
				else
					$updateArray["useWikindxKey"] = 'N';
				continue;
			}
			if($pref == "useBibtexKey") // checkbox
			{
				if($this->session->getVar("setup_useBibtexKey"))
					$updateArray["useBibtexKey"] = 'Y';
				else
					$updateArray["useBibtexKey"] = 'N';
				continue;
			}
			if($pref == "displayBibtexLink") // checkbox
			{
				if($this->session->getVar("setup_displayBibtexLink"))
					$updateArray["displayBibtexLink"] = 'Y';
				else
					$updateArray["displayBibtexLink"] = 'N';
				continue;
			}
			if($pref == "displayCmsLink") // checkbox
			{
				if($this->session->getVar("setup_displayCmsLink"))
					$updateArray["displayCmsLink"] = 'Y';
				else
					$updateArray["displayCmsLink"] = 'N';
				continue;
			}
			if($value = $this->session->getVar("setup_" . $pref))
				$updateArray[$pref] = $value;
		}
		$this->db->update('WKX_users', $updateArray, " WHERE " . 
			$this->db->formatField('id') . " = " . $this->db->tidyInput($userId));
	}
// store user preferences in the session setup_ array
// Can come from WKX_users or WKX_config (default values for readOnly user in which case $userId = FALSE)
	function writeSessionPreferences($userId, $table = 'WKX_users')
	{
		if($table == 'WKX_users')
			$preferences = array("paging", "pagingMaxLinks", "stringLimit", "language", "style", "template", "pagingStyle", 
				"pagingTagCloud", "kwBibliography", "useBibtexKey", "useWikindxKey", "displayBibtexLink", "displayCmsLink", "cmsTag");
		else
			$preferences = array("paging", "pagingMaxLinks", "stringLimit", "language", "style", "template",
				"pagingTagCloud", "kwBibliography");
		$condition = $userId ? 
			" WHERE " . $this->db->formatField('id') . " = " . $this->db->tidyInput($userId) : FALSE;
		$recordset = $this->db->select(array($table), $preferences, $condition);
		if(!$this->db->numRows($recordset))
			return FALSE;
		$row = $this->db->fetchRow($recordset);
// Check requested style plug-in has not been deleted.  If so, return first in list so that something is safely 
// displayed when listing bibliographies.
		include_once("core/styles/LOADSTYLE.php");
		$styles = LOADSTYLE::loadDir("styles/bibliography");
		if(!array_key_exists($row['style'], $styles))
		{
			$styleKeys = array_keys($styles);
			$row['style'] = array_shift($styleKeys);
		}
		foreach($preferences as $pref)
		{
			if($pref == 'pagingStyle')
			{
				if($row['pagingStyle'] == 'A')
					$this->session->setVar("setup_pagingStyle", 'A');
				else
					$this->session->delVar("setup_pagingStyle");
				continue;
			}
			if($pref == 'kwBibliography')
			{
				if($row['kwBibliography'] == 'Y')
					$this->session->setVar("setup_kwBibliography", TRUE);
				else
					$this->session->delVar("setup_kwBibliography");
				continue;
			}
			if($pref == 'useWikindxKey')
			{
				if($row['useWikindxKey'] == 'Y')
					$this->session->setVar("setup_useWikindxKey", TRUE);
				else
					$this->session->delVar("setup_useWikindxKey");
				continue;
			}
			if($pref == 'useBibtexKey')
			{
				if($row['useBibtexKey'] == 'Y')
					$this->session->setVar("setup_useBibtexKey", TRUE);
				else
					$this->session->delVar("setup_useBibtexKey");
				continue;
			}
			if($pref == 'displayBibtexLink')
			{
				if($row['displayBibtexLink'] == 'Y')
					$this->session->setVar("setup_displayBibtexLink", TRUE);
				else
					$this->session->delVar("setup_displayBibtexLink");
				continue;
			}
			if($pref == 'displayCmsLink')
			{
				if($row['displayCmsLink'] == 'Y')
					$this->session->setVar("setup_displayCmsLink", TRUE);
				else
					$this->session->delVar("setup_displayCmsLink");
				continue;
			}
			if($pref == 'cmsTag')
			{
				if($row['cmsTag'])
				{
					$cms = unserialize(base64_decode($row['cmsTag']));
					$this->session->setVar("setup_cmsTagStart", $cms[0]);
					$this->session->setVar("setup_cmsTagEnd", $cms[1]);
				}
				else
				{
					$this->session->delVar("setup_cmsTagStart");
					$this->session->delVar("setup_cmsTagEnd");
				}
				continue;
			}
			$this->session->setVar("setup_" . $pref, $row[$pref]);
		}
// The system also requires userRegistration, notify, multiUser, maxPaste fileAttach and fileViewLoggedOnOnly etc. from 
// WKX_config
		$recordset = $this->db->select(array('WKX_config'), array('userRegistration', 'multiUser', 'notify', 
			'fileAttach', 'fileViewLoggedOnOnly', 'maxPaste', 'lastChanges', 'lastChangesType', 'importBib', 
			'lastChangesDayLimit'));
		$row = $this->db->fetchRow($recordset);
		if($row['userRegistration'] == 'Y')
			$this->session->setVar("setup_userRegistration", TRUE);
		if($row['multiUser'] == 'Y')
			$this->session->setVar("setup_multiUser", TRUE);
		if($row['notify'] == 'Y')
			$this->session->setVar("setup_notify", TRUE);
		if($row['fileAttach'] == 'Y')
			$this->session->setVar("setup_fileAttach", TRUE);
		if($row['fileViewLoggedOnOnly'] == 'Y')
			$this->session->setVar("setup_fileViewLoggedOnOnly", TRUE);
		if($row['importBib'] == 'Y')
			$this->session->setVar("setup_importBib", TRUE);
		$this->session->setVar("setup_maxPaste", $row['maxPaste']);
		$this->session->setVar("setup_lastChanges", $row['lastChanges']);
		$this->session->setVar("setup_lastChangesDayLimit", $row['lastChangesDayLimit']);
		$this->session->setVar("setup_lastChangesType", $row['lastChangesType']);
// set setup_bibliographies to TRUE if there exist populated user bibliographies (used in MENU.php)
		$recordset = $this->db->select(array('WKX_user_bibliography'), array('id'), 
			" WHERE " . $this->db->formatField('bibliography') . ' IS NOT NULL');
		if($this->db->numRows($recordset))
			$this->session->setVar("setup_bibliographies", TRUE);
		return TRUE;
	}
// ensure we are allowed to edit/delete this user
	function gateKeep($method)
	{
		if(!$this->session->getVar("setup_superadmin") && !$this->session->getVar("setup_userId"))
		{
			include_once("core/authorize/AUTHORIZE.php");
			$authorize = new AUTHORIZE($this->db);
			if($pString = $authorize->initLogon())
				return $pString;
		}
// else, run $method
		return $this->$method();
	}
// Set the forget password system's questions and answers
	function forgetSet()
	{
		$array = array("question1", "answer1", "question2", "answer2", "question3", "answer3");
		$this->writeSession($array);
		if($error = $this->validateInput('forget'))
			$this->badInput($error, "initDisplay");
		$userId = $this->session->getVar("setup_userId");
// When writing to db, ensure $answer is lowercased, trimmed and sha1() encrypted
		for($i = 1; $i < 4; $i++)
		{
			$question = "passwordQuestion$i";
			$$question = trim($this->vars["passwordQuestion$i"]);
			if(!$$question)
				continue;
			$update = $fields = $values = array();
			$answer = "answer$i";
			$$answer = trim($this->vars["answer$i"]);
			$update["passwordQuestion$i"] = $$question;
			$update["passwordAnswer$i"] = sha1(strtolower($$answer));
			$this->db->update('WKX_users', $update, 
				" WHERE " . $this->db->formatField('id') . " = " . $this->db->tidyInput($userId));
			$this->session->delVar("mywikindx_question$i");
			$this->session->delVar("mywikindx_answer$i");
		}
		$this->template->setVar("heading", $this->messages->text("heading", "myWikindx"));
		$pString = $this->success->text("forgetUpdate");
		include_once("core/html/CLOSE.php");
		new CLOSE($this->db, $this->initDisplay($pString));
	}
// edit user details
	function userEdit()
	{
		$userArray = array("password", "email", "fullname");
		$this->writeSession($userArray);
		if($error = $this->validateInput('user'))
			$this->badInput($error, "initDisplay");
// all clear to write to database and send email
// Write to database. writeUser() returns FALSE on success, TRUE on failure!
		if($error = $this->writeUser(FALSE, 0))
			$this->badInput($error, "initDisplay");
		include_once("core/email/EMAIL.php");
		$emailClass = new EMAIL(FALSE, $this->vars);
		$emailClass->userEdit();
		$this->template->setVar("heading", $this->messages->text("heading", "myWikindx"));
		$pString = $this->success->text("user", " " . $this->messages->text("misc", "edited") . " ");
		include_once("core/html/CLOSE.php");
		new CLOSE($this->db, $this->initDisplay($pString));
	}
// check for valid input
	function validateInput($type)
	{
		if($type == 'user')
		{
			if(!trim($this->vars['password']) || !trim($this->vars['passwordConfirm']))
				return $this->errors->text("inputError", "missing");
			if(trim($this->vars['password']) != trim($this->vars['passwordConfirm']))
				return $this->errors->text("inputError", "invalid");
			if((!array_key_exists('email', $this->vars) || 
				!trim($this->vars['email'])))
				return $this->errors->text("inputError", "missing");
		}
		else if($type == 'forget')
		{
			$input1 = $input2 = $input3 = FALSE;
			for($i = 1; $i < 4; $i++)
			{
				$question = trim($this->vars["passwordQuestion$i"]);
				$answer = trim($this->vars["answer$i"]);
				if($question && $answer)
				{
					$input = "input" . $i;
					$$input = TRUE;
				}
				if(!$question)
					$this->session->delVar("mywikindx_passwordQuestion$i");
				if(!$answer)
					$this->session->delVar("mywikindx_answer$i");
			}
			if(!$input1 && !$input2 && !$input3)
				return $this->errors->text("inputError", "missing");
		}
// FALSE = validated!
		return FALSE;
	}
// display myWikindx user details for editing
	function initDisplay($error = FALSE)
	{
		include_once("core/user/MYWIKINDX.php");
		$bib = new MYWIKINDX($this->db, $this->vars);
		global $WIKINDX_RESTRICT_USER;
		$this->template->setVar("heading", $this->messages->text("heading", "myWikindx"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$this->loadSession();
/**
* For a test user (see index.php)
*/
		if($WIKINDX_RESTRICT_USER)
		{
			if($this->session->getVar('setup_userId') != $WIKINDX_RESTRICT_USER)
			{
				$pString .= $this->displayUserDetails("myWikindxUserEdit");
				$pString .= MISC::br() . MISC::hr() . MISC::br();
				$pString .= $this->forget();
				$pString .= MISC::br() . MISC::hr() . MISC::br();
// in case superadmin has not entered email yet or notification is disabled
				if($this->session->issetVar("mywikindx_email") && $this->session->issetVar("setup_notify"))
				{
					$pString .= $this->displayNotify("myWikindxNotifyEdit");
					$pString .= MISC::br() . MISC::hr() . MISC::br();
				}
			}
		}
		else
		{
			$pString .= $this->displayUserDetails("myWikindxUserEdit");
			$pString .= MISC::br() . MISC::hr() . MISC::br();
			$pString .= $this->forget();
			$pString .= MISC::br() . MISC::hr() . MISC::br();
// in case superadmin has not entered email yet or notification is disabled
			if($this->session->issetVar("mywikindx_email") && $this->session->issetVar("setup_notify")) 
			{
				$pString .= $this->displayNotify("myWikindxNotifyEdit");
				$pString .= MISC::br() . MISC::hr() . MISC::br();
			}
		}
		$pString .= $bib->listUserGroups();
		$pString .= MISC::br() . MISC::hr() . MISC::br();
		$pString .= $bib->listBibliographies();
		$pString .= MISC::br() . MISC::hr() . MISC::br();
		$pString .= $bib->listGroupBibliographies();
		$pString .= MISC::br() . MISC::hr() . MISC::br();
		$pString .= $bib->useBibInit();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Load user details into session mywikindx_ array
	function loadSession($id = FALSE)
	{
		if(!$id)
			$id = $this->session->getVar("setup_userId");
		$userArray = array("username", "password", "email", "fullname", "admin", "cookie");
		for($i = 1; $i < 4; $i++)
			$userArray[] = "passwordQuestion$i";
		$condition = " WHERE " . $this->db->formatField('id') . " = " . 
			$this->db->tidyInput($id);
		$recordset = $this->db->select(array('WKX_users'), $userArray, $condition);
		if(!$this->db->numRows($recordset))
			$this->failure($this->errors->text("sessionError", "write"));
		$row = $this->db->fetchRow($recordset);
		foreach($userArray as $key)
		{
			if(($key == 'admin') || ($key == 'cookie'))
			{
				if($row[$key] == 'Y')
					$this->session->setVar("mywikindx_" . $key, TRUE);
				else
					$this->session->delVar("mywikindx_" . $key);
				continue;
			}
			if($row[$key])
				$this->session->setVar("mywikindx_" . $key, $row[$key]);
		}
		$this->grabBibliographies($id);
	}
// Grab bibliographies from db and serialise to session
	function grabBibliographies($id = FALSE)
	{
		if(!$id)
			$id = $this->session->getVar("setup_userId");
		$condition = " WHERE " . $this->db->formatField('userId') . " = " . 
			$this->db->tidyInput($id);
		$recordset = $this->db->select(array('WKX_user_bibliography'), array('id', 'title', 'userGroupId'), 
			$condition);
		while($row = $this->db->loopRecordSet($recordset))
		{
			if(!$row['userGroupId'])
				$ids[$row['id']] = $row['title'];
			else
				$groupIds[$row['id']] = $row['title'];
		}
		if(isset($ids))
			$this->session->setVar("mywikindx_bibliographies", serialize($ids));
		else
			$this->session->delVar("mywikindx_bibliographies");
		if(isset($groupIds))
			$this->session->setVar("mywikindx_groupbibliographies", serialize($groupIds));
		else
			$this->session->delVar("mywikindx_groupbibliographies");
	}
// display form for entering questions and answers for a forgotten password scenario
	function forget()
	{
		$pString = FORM::formHeader("forgetSet");
		$pString .= MISC::p(MISC::b($this->messages->text("heading", "forget")));
		$pString .= MISC::p($this->messages->text("user", "forget1"));
		$pString .= MISC::p($this->messages->text("user", "forget5"));
		$pString .= MISC::p($this->messages->text("user", "forget2"));
		for($i = 1; $i < 4; $i++)
		{
			$question = $this->session->issetVar("mywikindx_passwordQuestion$i") ? 
				$this->html->dbToFormTidy($this->session->getVar("mywikindx_passwordQuestion$i")) : FALSE;
			$answer = $this->session->issetVar("mywikindx_answer$i") ? 
				$this->html->dbToFormTidy($this->session->getVar("mywikindx_answer$i")) : FALSE;
			$string = FORM::textInput($this->messages->text("user", "forget3", "&nbsp;" . $i), 
				"passwordQuestion$i", $question, 100, 255);
			$string .= MISC::br() . FORM::textInput($this->messages->text("user", "forget4", "&nbsp;" . $i), 
				"answer$i", $answer, 50, 100);
			$pString .= MISC::p($string);
		}
		$pString .= MISC::p(FORM::formSubmit("Proceed"), FALSE, "right");
		$pString .= FORM::formEnd();
		return $pString;
	}
// display user details from WKX_users
// If $admin != FALSE, it is the user id that an admin is editing
	function displayUserDetails($form, $admin = FALSE)
	{
		$pString = FORM::formHeader($form);
		$pString .= TABLE::tableStart();
		$pString .= TABLE::trStart();
		$sessVar = $this->session->issetVar("mywikindx_username") ? 
			$this->html->dbToFormTidy($this->session->getVar("mywikindx_username")) : FALSE;
		$pString .= FORM::hidden("uname", $sessVar);
		$pString .= TABLE::td(MISC::b($this->messages->text("user", "username")) . ":&nbsp;&nbsp;$sessVar" . 
			MISC::br() . "&nbsp;");
		$pString .= TABLE::trEnd();
		$pString .= TABLE::trStart();
		$sessVar = $this->session->issetVar("mywikindx_password") ? 
			$this->html->dbToFormTidy($this->session->getVar("mywikindx_password")) : FALSE;
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "password"), 
			"password", $sessVar, 15, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "passwordConfirm"), 
		"passwordConfirm", $sessVar, 15, 255) . " " . MISC::span('*', 'required'));
		$sessVar = $this->session->issetVar("mywikindx_email") ? 
			$this->html->dbToFormTidy($this->session->getVar("mywikindx_email")) : FALSE;
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "email"), "email", $sessVar, 30, 255)
			 . " " . MISC::span('*', 'required'));
		$sessVar = $this->session->issetVar("mywikindx_fullname") ? 
			$this->html->dbToFormTidy($this->session->getVar("mywikindx_fullname")) : FALSE;
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "fullname"), 
			"fullname", $sessVar, 20, 255));
		if($admin)
		{
			$pString .= FORM::hidden("userId", $admin);
			$pString .= TABLE::tableStart();
			$pString .= TABLE::trStart();
			$sessVar = $this->session->issetVar("mywikindx_admin") ? 
				'CHECKED' : FALSE;
			$pString .= TABLE::td(FORM::checkbox($this->messages->text("user", "admin"), "admin", $sessVar));
		}
		else
		{
			$sessVar = $this->session->issetVar("mywikindx_cookie") ? 
				'CHECKED' : FALSE;
			$pString .= TABLE::td(FORM::checkbox($this->messages->text("user", "cookie"), "cookie", $sessVar));
		}
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		$pString .= MISC::p(FORM::formSubmit("Edit"), FALSE, "right");
		$pString .= FORM::formEnd();
		return $pString;
	}
	function displayNotify($form)
	{
		$pString = TABLE::tableStart();
		$pString .= TABLE::trStart();
		$pString .= FORM::formHeader($form);
		$pString .= FORM::hidden("method", "notify");
		$pString .= MISC::p(MISC::b($this->messages->text("user", "notification")));
		if(!$this->session->getVar("mywikindx_notify"))
		{
			$recordset = $this->db->select(array('WKX_users'), array('notify', 'notifyAddEdit', 
				'notifyThreshold', 'notifyTimestamp'), 
				" WHERE " . $this->db->formatField('id') . "=" . 
				$this->db->tidyInput($this->session->getVar('setup_userId')));
			$row = $this->db->fetchRow($recordset);
			$this->session->setVar("mywikindx_notify", $row['notify']);
			if($row['notifyAddEdit'] == 'A')
			{
				$this->session->setVar("mywikindx_notifyAdd", TRUE);
				$this->session->setVar("mywikindx_notifyEdit", TRUE);
			}
			else if($row['notifyAddEdit'] == 'N')
			{
				$this->session->setVar("mywikindx_notifyAdd", TRUE);
				$this->session->delVar("mywikindx_notifyEdit");
			}
			else if($row['notifyAddEdit'] == 'E')
			{
				$this->session->setVar("mywikindx_notifyEdit", TRUE);
				$this->session->delVar("mywikindx_notifyAdd");
			}
			$this->session->setVar("mywikindx_notifyThreshold", $row['notifyThreshold']);
			$this->session->setVar("mywikindx_notifyTimestamp", $row['notifyTimestamp']);
		}
		$checked = $this->session->getVar("mywikindx_notify") == 'N' ? TRUE : FALSE;
		$pString .= TABLE::tdStart();
		$pString .= MISC::p(FORM::radioButton(FALSE, "notify", "N", $checked) . "&nbsp;&nbsp;" . 
			$this->messages->text("user", "notifyNone"));
		$checked = $this->session->getVar("mywikindx_notify") == 'A' ? TRUE : FALSE;
		$pString .= MISC::p(FORM::radioButton(FALSE, "notify", "A", $checked) . "&nbsp;&nbsp;" . 
			$this->messages->text("user", "notifyAll"));
		$checked = $this->session->getVar("mywikindx_notify") == 'M' ? TRUE : FALSE;
		$pString .= MISC::p(FORM::radioButton(FALSE, "notify", "M", $checked) . "&nbsp;&nbsp;" . 
			$this->messages->text("user", "notifyMy"));
		$add = $this->session->issetVar("mywikindx_notifyAdd") ? 'CHECKED' : FALSE;
		$edit = $this->session->issetVar("mywikindx_notifyEdit") ? 'CHECKED' : FALSE;
		$pString .= MISC::p($this->messages->text("user", "notifyAdd") . ":&nbsp;&nbsp;" . 
			FORM::checkbox(FALSE, "notifyAdd", $add) . MISC::br() . 
			$this->messages->text("user", "notifyEdit") . ":&nbsp;&nbsp;" . 
			FORM::checkbox(FALSE, "notifyEdit", $edit));
		$pString .= TABLE::tdEnd();
		$pString .= TABLE::tdStart();
		$array = array(0 => $this->messages->text("user", "notifyImmediate"), 1 => 1, 7 => 7, 14 => 14, 28 => 28);
		$selected = $this->session->getVar('mywikindx_notifyThreshold');
		if($selected)
			$pString .= MISC::p(FORM::selectedBoxValue($this->messages->text("user", "notifyThreshold"), 
			"notifyThreshold", $array, $selected, 5));
		else
			$pString .= MISC::p(FORM::selectFBoxValue($this->messages->text("user", "notifyThreshold"), 
			"notifyThreshold", $array, 5));
		$pString .= MISC::p(FORM::formSubmit("Proceed"), FALSE, "right");
		$pString .= FORM::formEnd();
		$pString .= TABLE::tdEnd();
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		return $pString;
	}
// write session details
	function writeSession($array)
	{
		foreach($array as $key)
		{
			if(array_key_exists($key, $this->vars) && $this->vars[$key])
				$this->session->setVar("mywikindx_" . $key, $this->vars[$key]);
		}
	}
// Delete user(s) from user table.  $input is array of ids in WKX_users.
	function deleteSql($input)
	{
// Delete from WKX_users and optimize table
		foreach($input as $id)
		{
			$this->db->delete('WKX_users', "WHERE " . $this->db->formatfield('id') . "=" . 
				$this->db->tidyInput($id));
		}
		$this->db->optimize('WKX_users');
// Delete from WKX_user_bibliography and optimize table
		foreach($input as $id)
			$this->db->delete('WKX_user_bibliography', "WHERE " . $this->db->formatfield('userId') . "=" . 
				$this->db->tidyInput($id));
		$this->db->optimize('WKX_user_bibliography');
// Unlink papers, delete from WKX_papers and optimize table
		foreach($input as $id)
		{
			$recordSet = $this->db->select(array("WKX_papers"), array('hashFilename'), 
				" WHERE " . $this->db->formatField('userId') . '=' . $this->db->tidyInput($id));
			while($row = $this->db->loopRecordSet($recordSet))
			{
				$file = "papers/" . $row['hashFilename'];
				@unlink($file);
			}
			$this->db->delete('WKX_papers', "WHERE " . $this->db->formatfield('userId') . "=" . 
				$this->db->tidyInput($id));
		}
		$this->db->optimize('WKX_papers');
		return TRUE;
	}
// create 'added by..., edited by... details for displaying one resource
	function displayUserAddEdit($addId, $editId = FALSE, $plain = FALSE, $timestamp = FALSE, 
		$timestampAdd = FALSE, $popularityIndex = FALSE)
	{
		$user = '';
		if(!$this->session->getVar('setup_multiUser'))
			return $user;
		$user = $userAdd = $userEdit = FALSE;
		if($addId)
		{
			$recordset = $this->db->select(array('WKX_users'), array('username', 'fullname'), 
				" WHERE " . $this->db->formatField('id') . "=" . $this->db->tidyInput($addId));
			$row2 = $this->db->fetchRow($recordset);
			if($row2['fullname'])
				$userAdd = $this->messages->text("hint", "addedBy", ": " . $row2['fullname'] . $timestampAdd);
			else if($row2['username'])
				$userAdd = $this->messages->text("hint", "addedBy", ": " . $row2['username'] . $timestampAdd);
			else
				$userEdit = $this->messages->text("hint", "addedBy", ": " . 
				$this->messages->text("user", "unknown") . $timestampAdd);
		}
		if($editId)
		{
			$recordset = $this->db->select(array('WKX_users'), array('username', 'fullname'), 
				" WHERE " . $this->db->formatField('id') . "=" . $this->db->tidyInput($editId));
			$row2 = $this->db->fetchRow($recordset);
			if($row2['fullname'])
				$userEdit = $this->messages->text("hint", "editedBy", ": " . $row2['fullname'] . $timestamp);
			else if($row2['username'])
				$userEdit = $this->messages->text("hint", "editedBy", ": " . $row2['username'] . $timestamp);
			else
				$userAdd = $this->messages->text("hint", "editedBy", ": " . 
				$this->messages->text("user", "unknown") . $timestamp);
		}
		if($userAdd && $userEdit)
		{
			if($plain)
				$user = $userAdd . "    " . $userEdit;
			else
				$user = MISC::br() . $userAdd . "&nbsp;&nbsp;&nbsp;&nbsp;" . $userEdit;
		}
		else if($userAdd)
		{
			if($plain)
				$user = $userAdd;
			else
				$user = MISC::br() . $userAdd;
		}
		else if($userEdit)
		{
			if($plain)
				$user = $userEdit;
			else
				$user = MISC::br() . $userEdit;
		}
		if($popularityIndex)
			$user .= MISC::span("&nbsp;&nbsp;&nbsp;&nbsp;" . 
			$this->messages->text('viewResource', 'popularity', ":&nbsp;&nbsp;" . $popularityIndex), 'hint');
		return $user;
	}
// create username - plain version of above used in core/notify/NOTIFY.php
	function displayUserAddEditPlain($addId)
	{
		$user = $userAdd = FALSE;
		if($addId)
		{
			$recordset = $this->db->select(array('WKX_users'), array('username', 'fullname'), 
				" WHERE " . $this->db->formatField('id') . "=" . $this->db->tidyInput($addId));
			$row2 = $this->db->fetchRow($recordset);
			if($row2['fullname'])
				$userAdd = $row2['fullname'];
			else if($row2['username'])
				$userAdd = $row2['username'];
			else
				$userEdit = $this->messages->text("user", "unkown");
		}
		if($userAdd)
			return $userAdd;
		return $user;
	}
// failure - bomb out
	function failure($error)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "myWikindx"));
		include_once("core/html/CLOSE.php");
		$this->template->setVar('body', $error);
		new CLOSE($this->db, $this->template->process());
	}
// bad Input function
	function badInput($error, $method)
	{
		include_once("core/html/CLOSE.php");
		new CLOSE($this->db, $this->$method($error));
	}
}
